home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / dos / matchpattern.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-12  |  8.6 KB  |  308 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: matchpattern.c,v 1.1 1996/09/11 12:54:46 digulla Exp $
  4.     $Log: matchpattern.c,v $
  5.     Revision 1.1  1996/09/11 12:54:46  digulla
  6.     A couple of new DOS functions from M. Fleischer
  7.  
  8.     Desc:
  9.     Lang: english
  10. */
  11. #include <exec/memory.h>
  12. #include <clib/exec_protos.h>
  13. #include <dos/dosextens.h>
  14. #include "dos_intern.h"
  15.  
  16. /*****************************************************************************
  17.  
  18.     NAME */
  19.     #include <clib/dos_protos.h>
  20.  
  21.     __AROS_LH2(BOOL, MatchPattern,
  22.  
  23. /*  SYNOPSIS */
  24.     __AROS_LHA(STRPTR, pat, D1),
  25.     __AROS_LHA(STRPTR, str, D2),
  26.  
  27. /*  LOCATION */
  28.     struct DosLibrary *, DOSBase, 141, Dos)
  29.  
  30. /*  FUNCTION
  31.  
  32.     INPUTS
  33.  
  34.     RESULT
  35.  
  36.     NOTES
  37.  
  38.     EXAMPLE
  39.  
  40.     BUGS
  41.  
  42.     SEE ALSO
  43.  
  44.     INTERNALS
  45.  
  46.     HISTORY
  47.     29-10-95    digulla automatically created from
  48.                 dos_lib.fd and clib/dos_protos.h
  49.  
  50. *****************************************************************************/
  51. {
  52.     __AROS_FUNC_INIT
  53.     __AROS_BASE_EXT_DECL(struct DosLibrary *,DOSBase)
  54.  
  55.     /*
  56.         A simple method for pattern matching with multiple wildcards:
  57.         I use markers that consist of both a pointer into the string
  58.         and one into the pattern. The marker simply follows the string
  59.         and everytime it hits a wildcard it's split into two new markers
  60.         (one to assume that the wildcard match has ended and one to assume
  61.          that it continues). If a marker doesn't fit any longer it's
  62.         removed and if all of them are gone the pattern mismatches.
  63.         OTOH if any of the markers reaches the end of both the string
  64.         and the pattern simultaneously the pattern matches the string.
  65.     */
  66.     STRPTR s;
  67.     LONG match=0;
  68.     struct markerarray ma, *macur=&ma, *cur2;
  69.     LONG macnt=0, cnt2;
  70.     ULONG level;
  71.     UBYTE a, b, c, t;
  72.     LONG error;
  73. #define ERROR(a) { error=(a); goto end; }
  74.  
  75.     ma.next=ma.prev=NULL;
  76.     for(;;)
  77.         switch(*pat)
  78.         {
  79.             case MP_MULT: /* _#(_a) */
  80.                 /* Split the marker */
  81.                 PUSH(0,++pat,str);
  82.                 level=1;
  83.                 for(;;)
  84.                 {
  85.                     c=*pat++;
  86.                     if(c==MP_MULT)
  87.                         level++;
  88.                     else if(c==MP_MULT_END)
  89.                         if(!--level)
  90.                             break;
  91.                 }
  92.                 break;
  93.             case MP_MULT_END: /* #(a_)_ */
  94.                 /* Go back to the start of the block */
  95.                 level=1;
  96.                 for(;;)
  97.                 {
  98.                     c=*--pat;
  99.                     if(c==MP_MULT_END)
  100.                         level++;
  101.                     else if(c==MP_MULT)
  102.                         if(!--level)
  103.                             break;
  104.                 }
  105.                 break;
  106.             case MP_NOT: /* _~(_a) */
  107.                 s=++pat;
  108.                 level=1;
  109.                 for(;;)
  110.                 {
  111.                     c=*s++;
  112.                     if(c==MP_NOT)
  113.                         level++;
  114.                     else if(c==MP_NOT_END)
  115.                         if(!--level)
  116.                             break;
  117.                 }
  118.                 PUSH(1,s,str);
  119.                 break;
  120.             case MP_NOT_END: /* ~(a_)_ */
  121.                 cnt2=macnt;
  122.                 cur2=macur;
  123.                 do
  124.                 {
  125.                     cnt2--;
  126.                     if(cnt2<0)
  127.                     {
  128.                         cnt2=127;
  129.                         cur2=cur2->prev;
  130.                     }
  131.                 }while(!cur2->marker[cnt2].type);
  132.                 if(!*str++)
  133.                 {
  134.                     macnt=cnt2;
  135.                     macur=cur2;
  136.                 }else
  137.                     if(str>cur2->marker[cnt2].str)
  138.                         cur2->marker[cnt2].str=str;
  139.                 POP(t,pat,str);
  140.                 if(t&&*str)
  141.                 { PUSH(1,pat,str+1); }
  142.                 break;
  143.             case MP_OR: /* ( */
  144.                 s=++pat;
  145.                 level=1;
  146.                 for(;;)
  147.                 {
  148.                     c=*s++;
  149.                     if(c==MP_OR)
  150.                         level++;
  151.                     else if(c==MP_OR_NEXT)
  152.                     {
  153.                         if(level==1)
  154.                         { PUSH(0,s,str); }
  155.                     }else if(c==MP_OR_END)
  156.                         if(!--level)
  157.                             break;
  158.                 }
  159.                 break;
  160.             case MP_OR_NEXT: /* | */
  161.                 pat++;
  162.                 level=1;
  163.                 for(;;)
  164.                 {
  165.                     c=*pat++;
  166.                     if(c==MP_OR)
  167.                         level++;
  168.                     else if(c==MP_OR_END)
  169.                         if(!--level)
  170.                             break;
  171.                 }
  172.                 break;
  173.             case MP_OR_END: /* ) */
  174.                 pat++;
  175.                 break;
  176.             case MP_SINGLE: /* ? */
  177.                 pat++;
  178.                 if(*str)
  179.                     str++;
  180.                 else
  181.                 {
  182.                     POP(t,pat,str);
  183.                     if(t&&*str)
  184.                     { PUSH(1,pat,str+1); }
  185.                 }
  186.                 break;
  187.             case MP_SET: /* [ */
  188.                 pat++;
  189.                 for(;;)
  190.                 {
  191.                     a=b=*pat++;
  192.                     if(a==MP_SET_END)
  193.                     {
  194.                         POP(t,pat,str);
  195.                         if(t&&*str)
  196.                         { PUSH(1,pat,str+1); }
  197.                         break;
  198.                     }
  199.                     if(a==MP_ESCAPE)
  200.                         a=b=*pat++ +0x80;
  201.                     else if(a==MP_DASH)
  202.                     {
  203.                         a=*pat++;
  204.                         if(a==MP_ESCAPE)
  205.                             a=*pat++ +0x80;
  206.                         b=*pat++;
  207.                         if(b==MP_ESCAPE)
  208.                             b=*pat++ +0x80;
  209.                     }
  210.                     if(*str>=a&&*str<=b)
  211.                     {
  212.                         str++;
  213.                         while(*pat++!=MP_SET_END)
  214.                             ;
  215.                         break;
  216.                     }
  217.                 }
  218.                 break;
  219.             case MP_NOT_SET: /* [~ */
  220.                 if(!*str)
  221.                 {
  222.                     POP(t,pat,str);
  223.                     if(t&&*str)
  224.                     { PUSH(1,pat,str+1); }
  225.                     break;
  226.                 }
  227.                 pat++;
  228.                 for(;;)
  229.                 {
  230.                     a=b=*pat++;
  231.                     if(a==MP_SET_END)
  232.                     {
  233.                         str++;
  234.                         break;
  235.                     }
  236.                     if(a==MP_ESCAPE)
  237.                         a=b=*pat++ +0x80;
  238.                     else if(a==MP_DASH)
  239.                     {
  240.                         a=*pat++;
  241.                         if(a==MP_ESCAPE)
  242.                             a=*pat++ +0x80;
  243.                         b=*pat++;
  244.                         if(b==MP_ESCAPE)
  245.                             b=*pat++ +0x80;
  246.                     }
  247.                     if(*str>=a&&*str<=b)
  248.                     {
  249.                         POP(t,pat,str);
  250.                         if(t&&*str)
  251.                         { PUSH(1,pat,str+1); }
  252.                         break;
  253.                     }
  254.                 }
  255.                 break;
  256.             case MP_ALL: /* #? */
  257.                 /* This often used pattern has extra treatment to be faster */
  258.                 if(*str)
  259.                 { PUSH(0,pat,str+1); }
  260.                 pat++;
  261.                 break;
  262.             case 0:
  263.                 if(!*str)
  264.                 {
  265.                     match=1;
  266.                     ERROR(0);
  267.                 }else
  268.                 {
  269.                     POP(t,pat,str);
  270.                     if(t&&*str)
  271.                     { PUSH(1,pat,str+1); }
  272.                 }
  273.                 break;
  274.             case MP_ESCAPE:
  275.                 pat++;
  276.                 if(0x80+*pat++==*str)
  277.                     str++;
  278.                 else
  279.                 {
  280.                     POP(t,pat,str);
  281.                     if(t&&*str)
  282.                     { PUSH(1,pat,str+1); }
  283.                 }
  284.                 break;
  285.             default:
  286.                 if(*pat++==*str)
  287.                     str++;
  288.                 else
  289.                 {
  290.                     POP(t,pat,str);
  291.                     if(t&&*str)
  292.                     { PUSH(1,pat,str+1); }
  293.                 }
  294.                 break;
  295.         }
  296. end:
  297.     macur=ma.next;
  298.     while(macur!=NULL)
  299.     {
  300.         struct markerarray *next=macur->next;
  301.         FreeMem(macur,sizeof(struct markerarray));
  302.         macur=next;
  303.     }
  304.     ((struct Process *)FindTask(NULL))->pr_Result2=error;
  305.     return match;
  306.     __AROS_FUNC_EXIT
  307. } /* MatchPattern */
  308.